import { _decorator, Camera, Component, Prefab, Node, Label, ParticleSystem, instantiate, v3, AudioSource, v2, UITransform, tween, bezier } from 'cc';
import { DRUM_MAP } from './modules/DrumMap';
import { Drum } from './ctrl/Drum';
import { AudioManager } from '../../framework/manager/AudioManager';
const { ccclass, property } = _decorator;

@ccclass('DrumGame')
export class DrumGame extends Component {

    @property(Prefab)
    private guPrefabs: Prefab[]

    @property(Camera)
    private camera: Node

    private player: Node

    private gameState: boolean

    private bg: Node

    private userJump: boolean

    private score: number

    private scoreLabel: Label

    private scoreParticle: ParticleSystem

    private drumPosXSet: number[]
    private drumPosYSet: number[]
    private playerScaleX: number[]
    private drum_node: Node[]

    private prevPosX: number
    private prevPosY: number

    private actionTouch: Node

    private music: AudioSource

    private yourTurn: boolean

    private nextStep: number

    protected onLoad(): void {
        this.genDrumMap()

        this.player = this.node.getChildByPath("Player");
        this.player.active = true;
        this.gameState = false;

        this.bg = this.node.getChildByName("Bg")

        this.userJump = true;

        this.actionTouch = this.node.getChildByName("ActionTouch")
        this.actionTouch.on(Node.EventType.TOUCH_START, function () {
            if (this.game_stated === false) {
                this.startGame();
                return;
            }
            if (this.yourTurn === false) {
                return;
            }
            this.userJump = true;
        }.bind(this), this.actionTouch);

        this.music = this.node.getComponent(AudioSource);

        this.scoreLabel = this.node.getChildByPath("Score").getComponent(Label)
        this.scoreLabel.string = "0"

        this.score = 0

        this.scoreParticle = this.node.getChildByPath("Score/anim").getComponent(ParticleSystem)
    }

    protected start(): void {
        this.player.setPosition(DRUM_MAP.start_xpos, DRUM_MAP.start_ypos, 0)
        this.player.setScale(v3(this.playerScaleX[0], 1, 1))
    }

    jump_normal() {
        if (this.nextStep >= DRUM_MAP.data.length) { // 最后一个成功闯关
            this.gameState = false;
            AudioManager.Instance.playAudio("drum/sounds/jxm_01")
            return;
        }

        var w_pos, dst_pos, drum_pos;
        var game_over = false;

        this.player.setScale(v3(1, this.playerScaleX[this.nextStep], 1))

        if (DRUM_MAP.data[this.nextStep] === 0 || this.userJump === true) { // 正常的跳过
            drum_pos = v2(this.drumPosXSet[this.nextStep], this.drumPosYSet[this.nextStep]);
        }
        else { // 用户异常的跳过
            var x_offset = this.player.scale.x * 60;
            drum_pos = v2(this.drumPosXSet[this.nextStep] - x_offset, this.drumPosYSet[this.nextStep - 1] + DRUM_MAP.next_height[0]);
            game_over = true;
        }

        AudioManager.Instance.playAudio("drum/sounds/effect_jump_02")

        this.userJump = false;

        w_pos = this.camera.getComponent(UITransform).convertToWorldSpaceAR(drum_pos);
        dst_pos = this.player.parent.getComponent(UITransform).convertToNodeSpaceAR(w_pos);

        var start_pos = this.player.getPosition();
        var ctrl_x = (start_pos.x + dst_pos.x) * 0.5;
        var ctrl_y = dst_pos.y + 50;

        var bz_array = [v2(ctrl_x, ctrl_y), v2(ctrl_x, ctrl_y), dst_pos];
        var time = 0.6 + Math.random() * 0.2;
        var offset = 0.15;
 
        tween(this.player)
            // bezier(bz_array[0],bz_array[1],bz_array[2],bz_array[3],bz_array[4])
            .call(() => {
                this.drum_node[this.nextStep].getComponent(Drum).setJumped();
                this.nextStep++;
                this.score++;
                this.scoreLabel.string = "" + this.score;
                this.scoreParticle.clear();

                if (game_over) {
                    AudioManager.Instance.playAudio("drum/sounds/jxm_03")
 
                    tween(this.player).to(time, {position: v3(this.player.position.x, -640)})
                    .call(() => {
                        this.gameState = false;
                        tween(this.player.getChildByName("anim")).stop()
                        this.player.getChildByName("anim").angle = 0
                        this.music.stop();
                    }).start()

                    tween(this.player.getChildByName("anim"))
                        .by(1.2, {angle: 360})
                    .repeatForever().start()


                }
            })

            .delay(offset)
            .call(() => {
                if (game_over) { // 游戏结束,失败
                    return;
                }
                this.jump_normal();
            })

            .start


        this.player.getChildByName("anim").setScale(v3(1, 0.5, 1))
        tween(this.player.getChildByName("anim")).to(0.1, { scale: v3(0.7, 0.7, 1) }).start()

        // 开启判定
        this.yourTurn = false;

        tween(this.node).delay(time - offset).call(() => {
            this.yourTurn = true;
        }).start()

        // end 
    }

    startGame() {
        if (this.gameState === true) {
            return;
        }

        this.scoreLabel.string = "0";
        this.score = 0;

        this.music.stop();
        this.music.volume = 1;
        this.music.play();

        this.yourTurn = false;
        this.gameState = true;
        this.userJump = true;
        this.player.active = true;

        this.player.setPosition(v3(DRUM_MAP.start_xpos, DRUM_MAP.start_ypos, 0))
        this.player.setScale(v3(this.playerScaleX[0], 1, 1))
        this.drum_node[0].getComponent(Drum).setJumped();

        this.prevPosX = DRUM_MAP.start_xpos;
        this.prevPosY = DRUM_MAP.start_ypos;

        this.camera.setPosition(0, 0)

        this.bg.setPosition(0, -480, 0)

        this.nextStep = 1;
        this.jump_normal();
    }

    genDrumMap() {
        var xpos;
        var ypos;
        var dir = 0;
        var num = 0;
        var scaleX = 1;
        this.drumPosXSet = [];
        this.drumPosYSet = [];
        this.playerScaleX = [];

        this.drum_node = [];
        xpos = DRUM_MAP.start_xpos;
        ypos = DRUM_MAP.start_ypos;

        for (var i = 0; i < DRUM_MAP.data.length; i++) {
            var type = DRUM_MAP.data[i];
            var gu = instantiate(this.guPrefabs[type]);
            gu.active = true;
            this.camera.addChild(gu);
            gu.setPosition(v3(xpos, ypos, 0))

            this.drum_node.push(gu);
            this.drumPosXSet.push(xpos);
            this.drumPosYSet.push(ypos);
            this.playerScaleX.push(scaleX);
            num++;
            if (num >= 3) {
                dir = (dir === 0) ? 1 : 0;
                scaleX = scaleX * -1;
                num = 0;
            }


            if (i < DRUM_MAP.data.length - 1) {
                var next_type = DRUM_MAP.data[i + 1];
                // next的高度和位置
                if (dir === 0) {
                    xpos += 160;
                }
                else {
                    xpos -= 160;
                }
                ypos += DRUM_MAP.next_height[next_type];
            }
        }
    }

    protected update(dt: number): void {
        if (!this.gameState) {
            return;
        }
        var dy = this.prevPosY - this.player.position.y;


        this.prevPosY = this.player.position.y;

        let cameraPosY = this.camera.position.y;
        cameraPosY += dy;
        if (cameraPosY >= 0) {
            cameraPosY = 0;
        }
        this.camera.setPosition(this.camera.position.x, cameraPosY, 0)
        // 背景移动
        let bgY = this.bg.position.y + dy * 0.1
        if (bgY <= -1048) {
            bgY = -1048;
        }
        if (bgY >= -480) {
            bgY = -480;
        }
        this.bg.setPosition(this.bg.position.x, bgY, 0)
    }




}